<?php defined('SYSPATH') or die('No direct script access.') ;
/**
 * 支付宝支付 (直接付款)
 *
 * @author  Yellow.Chow <aultoale@gmail.com>
 * @version $Id: direct.php 197 2012-05-08 10:13:31Z yellow.chow $
 * @license http://www.gnu.org/licenses/gpl-3.0.html    GPL 3
 */
class Payment_Adapter_Alipay_Direct extends Payment_Adapter
{
    /**
     * 支付方式参数
     *
     * @var array
     */
    protected $_config = array(
        '_input_charset'    => 'utf-8', // 参数编码字符集
        'security_code'     => NULL, // 交易安全校验码
        /* 协议参数 */
        'service'           => 'create_direct_pay_by_user', // 接口名称
        'partner'           => NULL, // 合作伙伴 ID，合作伙伴在支付宝的用户 ID (16个数字字符)
        'notify_url'        => NULL, // 状态通知 URL，交易状态同步通知接收的 URL
        'return_url'        => NULL, // 支付响应 URL，处理完成后返回的 URL
        'sign_type'         => 'MD5', // 设定签名加密方式，(MD5/DSA) 目前仅支持 MD5
        /* 业务参数 */
        'subject'           => NULL, // 商名名称
        'body'              => NULL, // 商品描述
        'out_trade_no'      => NULL, // 外部交易号，格式：^[a-z0-9\-]{8,}$
        'show_url'          => NULL, // 商品展示网址
        'payment_type'      => 1, // 支付类型,
        'total_fee'         => NULL, // 订单总额
        'paymethod'         => 'directPay',// 付款方式 directPay:支付宝直接付款,bankPay:银行付款
        'defaultbank'       => NULL, // 银行代码
        /* 卖方信息 */
        'seller_email'      => NULL, // 卖家的支付宝注册 Email
    );

    /**
     * 设置订单编号
     *
     * @param  string  $id
     * @return Payment_Adapter_Alipay
     */
    public function set_id($id)
    {
        $this->_config['out_trade_no'] = $id;

        return $this;
    }

    /**
     * 设置订单主题
     *
     * @param  string  $subject
     * @return Payment_Adapter_Alipay
     */
    public function set_subject($subject)
    {
        $this->_config['subject'] = $subject;

        return $this;
    }

    /**
     * 设置订单描述
     *
     * @param  string  $body
     * @return Payment_Adapter_Alipay
     */
    public function set_body($body)
    {
        $this->_config['body'] = $body;

        return $this;
    }

    /**
     * 设置订单付款方式  directPay:支付宝直接付款,bankPay:银行付款
     *
     * @param  string  $paymethod
     * @return Payment_Adapter_Alipay
     */
    public function set_paymethod($paymethod)
    {
        $this->_config['paymethod'] = $paymethod;

        return $this;
    }

    /**
     * 设置付款银行
     *
     * @param  string  $defaultbank
     * @return Payment_Adapter_Alipay
     */
    public function set_defaultbank($defaultbank)
    {
        $this->_config['defaultbank'] = $defaultbank;

        return $this;
    }

    /**
     * 设置订单总金额
     *
     * @param  float  $amount
     * @return Payment_Adapter_Alipay
     */
    public function set_amount($amount)
    {
        $this->_config['total_fee'] = $amount;

        return $this;
    }

    /**
     * 设置安全校验码
     *
     * @param  string  $key
     * @return Payment_Adapter_Alipay
     */
    public function set_key($key)
    {
        $this->_config['security_code'] = $key;

        return $this;
    }

    /**
     * 获取支付网关地址
     *
     * @return string
     */
    public function get_gateway()
    {
        return 'https://www.alipay.com/cooperate/gateway.do';
    }

    /**
     * 获取基本参数
     *
     * @return array
     */
    protected function _get_params()
    {
        ksort($this->_config);
        reset($this->_config);

        $params = array();
        foreach ($this->_config as $key => $val)
        {
            if ($key != 'sign_type' AND $key != 'security_code' AND $val !== '' AND $val !== NULL)
            {
                $params[$key] = $val;
            }
        }

        return $params;
    }

    /**
     * 获取表单提交参数
     *
     * @return array
     */
    public function get_params()
    {
        return array_merge(
            $this->_get_params(),
            array(
                'sign' => $this->get_sign(),
                'sign_type' => 'MD5',
            )
        );
    }

    /**
     * 获取数字签名
     *
     * @return string
     */
    public function get_sign()
    {
        return md5(urldecode(http_build_query($this->_get_params())).$this->_config['security_code']);
    }

    /**
     * 获取支付 URL
     *
     * @return string
     */
    public function get_payurl()
    {
        return $this->get_gateway().'?'.http_build_query($this->get_params());
    }

    /**
     * 对参数进行校验
     *
     * @return bool
     */
    public function is_valid()
    {
        try
        {
            $config = $this->_config;

            // 字符集
            $config['_input_charset'] = strtolower($config['_input_charset']);
            if ($config['_input_charset'] != 'utf-8' AND $config['_input_charset'] != 'gbk')
            {
                throw new Payment_Exception('_input_charset：无效的参数编码字符集');
            }

            // 交易安全校验码
            if ( ! preg_match('/^[a-z0-9]{32}$/i', $config['security_code']))
            {
                throw new Payment_Exception('security_code：无效的安全校验码');
            }

            // 服务接口名称
            $config['service'] = strtolower($config['service']);

            // 合作伙伴 ID
            if ( ! preg_match('/^\d{16}$/', $config['partner']))
            {
                throw new Payment_Exception('partner：无效的合作伙伴 ID');
            }

            // 状态通知 URL
            if ( ! empty($config['notify_url']) AND ! Valid::url($config['notify_url']))
            {
                throw new Payment_Exception('notify_url：无效的状态通知 URL');
            }

            // 支付响应 URL
            if ( ! empty($config['return_url']) AND ! Valid::url($config['return_url']))
            {
                throw new Payment_Exception('return_url：无效的支付响应 URL');
            }

            // 签名加密方式
            $config['sign_type'] = strtoupper($config['sign_type']);
            if ($config['sign_type'] != 'MD5')
            {
                throw new Payment_Exception('sign_type：不支持的签名加密方式');
            }

            // 商品名称/订单主题
            $config['subject'] = Str::slice(trim(strip_tags($config['subject'])), 256);
            if (empty($config['subject']))
            {
                throw new Payment_Exception('subject：商品名称不能为空');
            }

            // 商品描述
            $config['body'] = Str::slice($config['body'], 400);

            // 外部交易号/订单编号
            if ( ! preg_match('/^[a-z0-9\-]{8,64}$/i', $config['out_trade_no']))
            {
                throw new Payment_Exception('out_trade_no：无效的订单编号');
            }

            // 商品单价/订单总金额
            if (floatval($config['total_fee']) <= 0)
            {
                throw new Payment_Exception('total_fee：无效的订单总金额');
            }

            // 商品展示 URL
            if ( ! empty($config['show_url']) AND ! Valid::url($config['show_url']))
            {
                throw new Payment_Exception('show_url：无效的商品展示 URL');
            }

            // 支付类型
            if (empty($config['payment_type']))
            {
                throw new Payment_Exception('payment_type：支付类型不能为空');
            }
            if ( ! in_array($config['payment_type'], array('1', '2', '3', '4', '5', '6')))
            {
                throw new Payment_Exception('payment_type：无效的支付类型');
            }

            // 卖家的支付宝注册 Email
            if ( ! empty($config['seller_email']) AND (strlen($config['seller_email']) > 100 OR ! Valid::email($config['seller_email'])))
            {
                throw new Payment_Exception('seller_email：无效的卖家支付宝注册 Email');
            }

            $this->_config = $config;

            return TRUE;
        }
        catch (Exception $e)
        {
            $this->_message = $e->getMessage();
            return FALSE;
        }
    }

    /**
     * 获取支付名称
     *
     * @return string
     */
    public function get_name()
    {
        return '支付宝即时到账';
    }
}